<!DOCTYPE html>
<!-- saved from url=(0080)https://juejin.im/book/5bdc715fe51d454e755f75ef/section/5bdc7207f265da613c09425d -->
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,viewport-fit=cover"><meta name="google-site-verification" content="cCHsgG9ktuCTgWgYfqCJql8AeR4gAne4DTZqztPoirE"><meta name="apple-itunes-app" content="app-id=987739104"><meta name="baidu-site-verification" content="qiK2a1kcFc"><meta name="360-site-verification" content="4c3c7d57d59f0e1a308462fbc7fd7e51"><meta name="sogou_site_verification" content="c49WUDZczQ"><style>body {
        font-size: 16px;
        line-height: 2;
      }
      a, button, input {
        margin: 1rem 1.5rem;
      }
      img {
        width: 0;
        height: 0;
      }
      #juejin {
        overflow-x: hidden;
      }</style><title data-vue-meta="true">前端面试之道 - yck - 掘金小册</title><link rel="apple-touch-icon" sizes="180x180" href="https://b-gold-cdn.xitu.io/favicons/v2/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="https://b-gold-cdn.xitu.io/favicons/v2/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="https://b-gold-cdn.xitu.io/favicons/v2/favicon-16x16.png"><link rel="manifest" href="https://b-gold-cdn.xitu.io/favicons/v2/manifest.json"><link rel="mask-icon" href="https://b-gold-cdn.xitu.io/favicons/v2/safari-pinned-tab.svg" color="#5bbad5"><link rel="shortcut icon" href="https://b-gold-cdn.xitu.io/favicons/v2/favicon.ico"><meta name="msapplication-config" content="https://b-gold-cdn.xitu.io/favicons/v2/browserconfig.xml"><meta name="theme-color" content="#ffffff"><link rel="search" title="掘金" href="https://b-gold-cdn.xitu.io/conf/search.xml" type="application/opensearchdescription+xml"><link rel="stylesheet" href="./13-浏览器渲染原理_files/ionicons.min.css"><link rel="stylesheet" href="./13-浏览器渲染原理_files/iconfont.css"><link href="./13-浏览器渲染原理_files/0.20e96f0e16539d696fbd.css" rel="stylesheet"><script async="" src="./13-浏览器渲染原理_files/hm.js.下载"></script><script async="" src="./13-浏览器渲染原理_files/analytics.js.下载"></script><script type="text/javascript" async="" src="./13-浏览器渲染原理_files/vds.js.下载"></script><script charset="utf-8" src="./13-浏览器渲染原理_files/13.46a6fc9d409a46c2798c.js.下载"></script><meta data-vmid="keywords" name="keywords" content="掘金,稀土,Vue.js,微信小程序,Kotlin,RxJava,React Native,Wireshark,敏捷开发,Bootstrap,OKHttp,正则表达式,WebGL,Webpack,Docker,MVVM" data-vue-meta="true"><meta data-vmid="description" name="description" content="掘金是一个帮助开发者成长的社区，是给开发者用的 Hacker News，给设计师用的 Designer News，和给产品经理用的 Medium。掘金的技术文章由稀土上聚集的技术大牛和极客共同编辑为你筛选出最优质的干货，其中包括：Android、iOS、前端、后端等方面的内容。用户每天都可以在这里找到技术世界的头条内容。与此同时，掘金内还有沸点、掘金翻译计划、线下活动、专栏文章等内容。即使你是 GitHub、StackOverflow、开源中国的用户，我们相信你也可以在这里有所收获。" data-vue-meta="true"></head><body><div id="juejin" data-v-514f306c=""><div class="global-component-box" data-v-514f306c=""><!----><div data-v-71cabb60="" data-v-514f306c="" class="alert-list alert-list"></div><!----><!----><!----><div class="emoji-barrage" data-v-e5f49d52="" data-v-514f306c=""><!----></div><div class="book-new-user-award-popup" style="display:none;" data-v-71b0e7b2="" data-v-514f306c=""><div class="content-box" style="display:;" data-v-71b0e7b2=""><div class="close ion-close-round" data-v-71b0e7b2=""></div><div class="header" data-v-71b0e7b2=""><div class="icon" data-v-71b0e7b2=""><img src="./13-浏览器渲染原理_files/icon.a87e5ae.svg" data-v-71b0e7b2=""></div><div class="txt" data-v-71b0e7b2="">新人专享好礼</div></div><div class="desc" data-v-71b0e7b2="">凡未购买过小册的用户，均可领取三张 5 折新人专享券，购买小册时自动使用专享券，最高可节省 45 元。</div><div class="tickets" data-v-71b0e7b2=""><div class="ticket" data-v-71b0e7b2=""><div class="ticket__inner" data-v-71b0e7b2=""><div class="enjoy" data-v-71b0e7b2=""><span class="new-title" data-v-71b0e7b2="">小册新人 5 折券</span></div><div class="sale" data-v-71b0e7b2="">最高可省 15 元</div></div></div><div class="ticket" data-v-71b0e7b2=""><div class="ticket__inner" data-v-71b0e7b2=""><div class="enjoy" data-v-71b0e7b2=""><span class="new-title" data-v-71b0e7b2="">小册新人 5 折券</span></div><div class="sale" data-v-71b0e7b2="">最高可省 15 元</div></div></div><div class="ticket" data-v-71b0e7b2=""><div class="ticket__inner" data-v-71b0e7b2=""><div class="enjoy" data-v-71b0e7b2=""><span class="new-title" data-v-71b0e7b2="">小册新人 5 折券</span></div><div class="sale" data-v-71b0e7b2="">最高可省 15 元</div></div></div></div><div class="remark" data-v-71b0e7b2="">注：专享券的使用期限在领券的七天内。</div><div class="submit-btn" data-v-71b0e7b2="">一键领取</div></div><div class="model success" style="display:none;" data-v-71b0e7b2=""><div class="heading" data-v-71b0e7b2="">领取成功</div><div class="content-text" data-v-71b0e7b2="">购买小册时自动使用专享券</div><div class="btn-success-footer" data-v-71b0e7b2=""><div class="btn-ok" data-v-71b0e7b2="">知道了</div><div class="btn-ok btn-link" data-v-71b0e7b2="">前往小册首页</div></div></div><div class="model fail" style="display:none;" data-v-71b0e7b2=""><div class="heading" data-v-71b0e7b2="">领取失败</div><div class="content-text" data-v-71b0e7b2="">本活动仅适用于小册新用户</div><div class="btn-ok" data-v-71b0e7b2="">知道了</div></div></div><!----></div><!----><div data-v-097468bb="" data-v-514f306c="" class="book-read-view"><section data-v-097468bb="" class="book-section"><div data-v-097468bb="" class="book-summary"><div data-v-097468bb="" class="book-summary-masker"></div><div data-v-097468bb="" class="book-summary-inner"><div data-v-097468bb="" class="book-summary__header"><a data-v-097468bb="" href="https://juejin.im/books" target="" rel="" class="logo"><img data-v-097468bb="" src="./13-浏览器渲染原理_files/logo.a7995ad.svg"></a><div data-v-097468bb="" class="label">小册</div><!----></div><!----><div data-v-d0eb2184="" data-v-097468bb="" class="book-directory book-directory bought"><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">1</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">小册食用指南</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">2</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">JS 基础知识点及常考面试题（一）</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">3</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">JS 基础知识点及常考面试题（二）</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">4</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">ES6 知识点及常考面试题</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">5</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">JS 异步编程及常考面试题</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">6</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">手写 Promise</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">7</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">Event Loop</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">8</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">JS 进阶知识点及常考面试题</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">9</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">JS 思考题</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">10</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">DevTools Tips</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">11</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">浏览器基础知识点及常考面试题</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link read"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">12</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">浏览器缓存机制</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section route-active section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">13</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">浏览器渲染原理</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">14</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">安全防范知识点</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">15</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">从 V8 中看 JS 性能优化</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">16</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">性能优化琐碎事</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">17</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">Webpack 性能优化</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">18</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">实现小型打包工具</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">19</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">React 和 Vue 两大框架之间的相爱相杀</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">20</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">Vue 常考基础知识点</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">21</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">Vue 常考进阶知识点</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">22</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">React 常考基础知识点</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">23</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">React 常考进阶知识点</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">24</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">监控</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">25</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">UDP</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">26</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">TCP</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">27</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">HTTP 及 TLS</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">28</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">HTTP/2 及 HTTP/3</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">29</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">输入 URL 到页面渲染的整个流程</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">30</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">设计模式</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">31</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">常见数据结构</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">32</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">常考算法题解析</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">33</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">CSS 常考面试题资料</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">34</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">如何写好一封简历</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">35</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">面试常用技巧</div><!----><!----></div><!----></a><a data-v-d0eb2184="" class="section section-link"><div data-v-d0eb2184="" class="step"><div data-v-d0eb2184="" class="step-btn">36</div></div><div data-v-d0eb2184="" class="center"><div data-v-d0eb2184="" class="title">前方的路，让我们结伴同行</div><!----><!----></div><!----></a></div><div data-v-097468bb="" class="book-summary__footer"><div data-v-097468bb="" class="qr-icon"><img data-v-097468bb="" src="./13-浏览器渲染原理_files/qr-icon.881015a.svg"></div><div data-v-097468bb="" class="qr-tips"><span data-v-097468bb="" class="ion-close"></span><div data-v-097468bb="" class="title"><span data-v-097468bb="">关注公众号</span><span data-v-097468bb="">领取优惠码</span></div><div data-v-097468bb="" class="qr-img"><img data-v-097468bb="" src="./13-浏览器渲染原理_files/wx-qr.13d8b4d.png"></div></div></div></div></div><div data-v-097468bb="" class="book-content"><div data-v-097468bb="" class="book-content-inner"><div data-v-097468bb="" class="book-content__header"><div data-v-097468bb="" class="switch"><img data-v-097468bb="" src="./13-浏览器渲染原理_files/icon.3e69d5a.svg"></div><div data-v-097468bb="" class="menu"><img data-v-097468bb="" src="./13-浏览器渲染原理_files/menu.74b9add.svg"></div><div data-v-097468bb="" class="title"><a data-v-097468bb="" href="https://juejin.im/book/5bdc715fe51d454e755f75ef" target="" rel="">前端面试之道</a></div><div data-v-629272fe="" data-v-097468bb="" class="user-auth user-auth"><div data-v-629272fe="" class="nav-item menu"><div data-v-3b1ba6d2="" data-v-afcc6e34="" data-v-629272fe="" data-src="https://b-gold-cdn.xitu.io/v3/static/img/default-avatar.e30559a.svg" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://b-gold-cdn.xitu.io/v3/static/img/default-avatar.e30559a.svg&quot;);"></div><div data-v-629272fe="" class="nav-menu user-dropdown-list" style="display: none;"><ul data-v-629272fe="" class="nav-menu-item-group"><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe=""><i data-v-629272fe="" class="fengwei fw-write"></i><span data-v-629272fe="">写文章</span></a></li><!----><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe=""><i data-v-629272fe="" class="fengwei fw-draft"></i><span data-v-629272fe="">草稿</span></a></li></ul><ul data-v-629272fe="" class="nav-menu-item-group"><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe="" href="https://juejin.im/user/5c2c54ca6fb9a049cb18da5a"><i data-v-629272fe="" class="fengwei fw-person"></i><span data-v-629272fe="">我的主页</span></a></li><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe="" href="https://juejin.im/user/5c2c54ca6fb9a049cb18da5a/likes"><i data-v-629272fe="" class="fengwei fw-like"></i><span data-v-629272fe="">我喜欢的</span></a></li><!----><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe="" href="https://juejin.im/user/5c2c54ca6fb9a049cb18da5a/collections"><i data-v-629272fe="" class="fengwei fw-collection"></i><span data-v-629272fe="">我的收藏集</span></a></li><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe="" href="https://juejin.im/user/5c2c54ca6fb9a049cb18da5a/books?type=bought"><i data-v-629272fe="" class="fengwei fw-bought"></i><span data-v-629272fe="">已购</span></a></li><!----><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe="" href="https://juejin.im/subscribe"><i data-v-629272fe="" class="fengwei fw-tag"></i><span data-v-629272fe="">标签管理</span></a></li></ul><ul data-v-629272fe="" class="nav-menu-item-group"><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe="" href="https://juejin.im/user/settings"><i data-v-629272fe="" class="fengwei fw-setting"></i><span data-v-629272fe="">设置</span></a></li><li data-v-629272fe="" class="nav-menu-item more"><a data-v-629272fe=""><i data-v-629272fe="" class="fengwei fw-info"></i><span data-v-629272fe="">关于</span><i data-v-629272fe="" class="ion-chevron-right more-icon"></i></a><div data-v-629272fe="" class="nav-menu more-dropdown-list"><ul data-v-629272fe="" class="nav-menu-item-group"><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe="" href="https://juejin.im/app" target="_blank">下载应用</a></li><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe="" href="https://juejin.im/about" target="_blank">关于</a></li><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe="" href="https://xitu.io/jobs" target="_blank">加入我们</a></li><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe="" href="https://github.com/xitu/gold-miner" rel="nofollow noopener noreferrer" target="_blank">翻译计划</a></li><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe="" href="https://bd.juejin.im/?utm_campaign=bd&amp;utm_source=web&amp;utm_medium=nav" target="_blank">合作伙伴</a></li></ul></div></li></ul><ul data-v-629272fe="" class="nav-menu-item-group"><li data-v-629272fe="" class="nav-menu-item"><a data-v-629272fe=""><i data-v-629272fe="" class="fengwei fw-logout"></i><span data-v-629272fe="">登出</span></a></li></ul></div></div><!----></div><!----></div><div data-v-097468bb="" class="book-body transition--next"><div data-v-5602b343="" data-v-097468bb="" class="section-view book-section-content"><div data-v-05bbf43a="" data-v-5602b343="" class="section-content"><div data-v-05bbf43a="" class="section-page book-section-view"><div data-v-05bbf43a="" class="entry-content article-content"><h1 class="heading" data-id="heading-0">浏览器渲染原理</h1>
<blockquote class="warning"><p>注意：该章节都是一个面试题。
</p></blockquote><p>在这一章节中，我们将来学习浏览器渲染原理这部分的知识。你可能会有疑问，我又不是做浏览器研发的，为什么要来学习这个？其实我们学习浏览器渲染原理更多的是为了解决性能的问题，如果你不了解这部分的知识，你就不知道什么情况下会对性能造成损伤。<strong>并且渲染原理在面试中答得好，也是一个能与其他候选人拉开差距的一点。</strong></p>
<p>我们知道执行 JS 有一个 JS 引擎，那么执行渲染也有一个渲染引擎。同样，渲染引擎在不同的浏览器中也不是都相同的。比如在 Firefox 中叫做 <strong>Gecko</strong>，在 Chrome 和 Safari 中都是基于 <strong>WebKit</strong> 开发的。在这一章节中，我们也会主要学习关于 <strong>WebKit</strong> 的这部分渲染引擎内容。</p>
<h2 class="heading" data-id="heading-1">浏览器接收到 HTML 文件并转换为 DOM 树</h2>
<p>当我们打开一个网页时，浏览器都会去请求对应的 HTML 文件。虽然平时我们写代码时都会分为 JS、CSS、HTML 文件，也就是字符串，但是计算机硬件是不理解这些字符串的，所以在网络中传输的内容其实都是 <code>0</code> 和 <code>1</code> 这些<strong>字节数据</strong>。当浏览器接收到这些字节数据以后，它会将这些<strong>字节数据转换为字符串</strong>，也就是我们写的代码。</p>
<p></p><figure><img class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2018/11/27/16754281e59587f3?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="369" data-height="91" src="./13-浏览器渲染原理_files/16754281e59587f3"><figcaption></figcaption></figure><p></p>
<p>当数据转换为字符串以后，浏览器会先将这些字符串通过词法分析转换为<strong>标记</strong>（token），这一过程在词法分析中叫做<strong>标记化</strong>（tokenization）。</p>
<p></p><figure><img class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2018/11/27/16754288f37a5347?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="496" data-height="80" src="./13-浏览器渲染原理_files/16754288f37a5347"><figcaption></figcaption></figure><p></p>
<p>那么什么是标记呢？这其实属于编译原理这一块的内容了。简单来说，标记还是字符串，是构成代码的<strong>最小单位</strong>。这一过程会将代码分拆成一块块，并给这些内容打上标记，便于理解这些最小单位的代码是什么意思。</p>
<p></p><figure><img class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2018/11/27/167540a7b5cef612?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="519" data-height="214" src="./13-浏览器渲染原理_files/167540a7b5cef612"><figcaption></figcaption></figure><p></p>
<p>当结束标记化后，这些标记会紧接着转换为 Node，最后这些 Node 会根据不同 Node 之前的联系构建为一颗 DOM 树。</p>
<p></p><figure><img class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2018/11/27/1675416cbea98c3c?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="622" data-height="274" src="./13-浏览器渲染原理_files/1675416cbea98c3c"><figcaption></figcaption></figure><p></p>
<p>以上就是浏览器从网络中接收到 HTML 文件然后一系列的转换过程。</p>
<p></p><figure><img class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2018/11/27/167542b09875a74a?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="794" data-height="141" src="./13-浏览器渲染原理_files/167542b09875a74a"><figcaption></figcaption></figure><p></p>
<p>当然，在解析 HTML 文件的时候，浏览器还会遇到 CSS 和 JS 文件，这时候浏览器也会去下载并解析这些文件，接下来就让我们先来学习浏览器如何解析 CSS 文件。</p>
<h2 class="heading" data-id="heading-2">将 CSS 文件转换为 CSSOM 树</h2>
<p>其实转换 CSS 到 CSSOM 树的过程和上一小节的过程是极其类似的</p>
<p></p><figure><img class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2018/11/27/167542a9af5f193f?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="778" data-height="155" src="./13-浏览器渲染原理_files/167542a9af5f193f"><figcaption></figcaption></figure><p></p>
<p>在这一过程中，浏览器会确定下每一个节点的<strong>样式</strong>到底是什么，并且这一过程其实是<strong>很消耗资源</strong>的。因为样式你可以自行设置给某个节点，也可以通过继承获得。在这一过程中，浏览器得<strong>递归</strong> CSSOM 树，然后确定具体的元素到底是什么样式。</p>
<p>如果你有点不理解为什么会消耗资源的话，我这里举个例子</p>
<pre><code class="hljs html" lang="html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-tag">span</span> {
    <span class="hljs-attribute">color</span>: red;
  }
  <span class="hljs-selector-tag">div</span> &gt; <span class="hljs-selector-tag">a</span> &gt; <span class="hljs-selector-tag">span</span> {
    <span class="hljs-attribute">color</span>: red;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre><p>对于第一种设置样式的方式来说，浏览器只需要找到页面中所有的 <code>span</code> 标签然后设置颜色，但是对于第二种设置样式的方式来说，浏览器首先需要找到所有的 <code>span</code> 标签，然后找到 <code>span</code> 标签上的 <code>a</code> 标签，最后再去找到 <code>div</code> 标签，然后给符合这种条件的 <code>span</code> 标签设置颜色，这样的递归过程就很复杂。所以我们应该尽可能的避免写<strong>过于具体</strong>的 CSS 选择器，然后对于 HTML 来说也尽量少的添加无意义标签，保证<strong>层级扁平</strong>。</p>
<h2 class="heading" data-id="heading-3">生成渲染树</h2>
<p>当我们生成 DOM 树和 CSSOM 树以后，就需要将这两棵树组合为渲染树。</p>
<p></p><figure><img class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2018/11/27/16754488529c48bd?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1150" data-height="537" src="./13-浏览器渲染原理_files/16754488529c48bd"><figcaption></figcaption></figure><p></p>
<p>在这一过程中，不是简单的将两者合并就行了。渲染树只会包括<strong>需要显示的节点</strong>和这些节点的样式信息，如果某个节点是 <code>display: none</code> 的，那么就不会在渲染树中显示。</p>
<p>当浏览器生成渲染树以后，就会根据渲染树来进行布局（也可以叫做回流），然后调用 GPU 绘制，合成图层，显示在屏幕上。对于这一部分的内容因为过于底层，还涉及到了硬件相关的知识，这里就不再继续展开内容了。</p>
<p>那么通过以上内容，我们已经详细了解到了浏览器从接收文件到将内容渲染在屏幕上的这一过程。接下来，我们将会来学习上半部分遗留下来的一些知识点。</p>
<h2 class="heading" data-id="heading-4">为什么操作 DOM 慢</h2>
<p>想必大家都听过操作 DOM 性能很差，但是这其中的原因是什么呢？</p>
<p>因为 DOM 是属于渲染引擎中的东西，而 JS 又是 JS 引擎中的东西。当我们通过  JS 操作 DOM 的时候，其实这个操作涉及到了两个线程之间的通信，那么势必会带来一些性能上的损耗。操作 DOM 次数一多，也就等同于一直在进行线程之间的通信，并且操作 DOM 可能还会带来重绘回流的情况，所以也就导致了性能上的问题。</p>
<blockquote class="warning"><p>经典面试题：插入几万个 DOM，如何实现页面不卡顿？
</p></blockquote><p>对于这道题目来说，首先我们肯定不能一次性把几万个 DOM 全部插入，这样肯定会造成卡顿，所以解决问题的重点应该是如何分批次部分渲染 DOM。大部分人应该可以想到通过 <code>requestAnimationFrame</code> 的方式去循环的插入 DOM，其实还有种方式去解决这个问题：<strong>虚拟滚动</strong>（virtualized scroller）。</p>
<p><strong>这种技术的原理就是只渲染可视区域内的内容，非可见区域的那就完全不渲染了，当用户在滚动的时候就实时去替换渲染的内容。</strong></p>
<p></p><figure><img class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2018/12/15/167b1c6887ecbba7?imageslim" data-width="1204" data-height="380" src="./13-浏览器渲染原理_files/167b1c6887ecbba7"><figcaption></figcaption></figure><p></p>
<p>从上图中我们可以发现，即使列表很长，但是渲染的 DOM 元素永远只有那么几个，当我们滚动页面的时候就会实时去更新 DOM，这个技术就能顺利解决这道经典面试题。如果你想了解更多的内容可以了解下这个 <a target="_blank" href="https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Fbvaughn%2Freact-virtualized" rel="nofollow noopener noreferrer">react-virtualized</a>。</p>
<h2 class="heading" data-id="heading-5">什么情况阻塞渲染</h2>
<p>首先渲染的前提是生成渲染树，所以 HTML 和 CSS 肯定会阻塞渲染。如果你想渲染的越快，你越应该降低一开始需要渲染的文件<strong>大小</strong>，并且<strong>扁平层级，优化选择器</strong>。</p>
<p>然后当浏览器在解析到 <code>script</code> 标签时，会暂停构建 DOM，完成后才会从暂停的地方重新开始。也就是说，如果你想首屏渲染的越快，就越不应该在首屏就加载 JS 文件，这也是都建议将 <code>script</code> 标签放在 <code>body</code> 标签底部的原因。</p>
<p>当然在当下，并不是说 <code>script</code> 标签必须放在底部，因为你可以给 <code>script</code> 标签添加 <code>defer</code> 或者 <code>async</code> 属性。</p>
<p>当 <code>script</code> 标签加上 <code>defer</code> 属性以后，表示该 JS 文件会并行下载，但是会放到 HTML 解析完成后顺序执行，所以对于这种情况你可以把 <code>script</code> 标签放在任意位置。</p>
<p>对于没有任何依赖的 JS 文件可以加上 <code>async</code> 属性，表示 JS 文件下载和解析不会阻塞渲染。</p>
<h2 class="heading" data-id="heading-6">重绘（Repaint）和回流（Reflow）</h2>
<p>重绘和回流会在我们设置节点样式时频繁出现，同时也会很大程度上影响性能。</p>
<ul>
<li>重绘是当节点需要更改外观而不会影响布局的，比如改变 <code>color</code> 就叫称为重绘</li>
<li>回流是布局或者几何属性需要改变就称为回流。</li>
</ul>
<p>回流<strong>必定</strong>会发生重绘，重绘<strong>不一定</strong>会引发回流。回流所需的成本比重绘高的多，改变父节点里的子节点很可能会导致父节点的一系列回流。</p>
<p>以下几个动作可能会导致性能问题：</p>
<ul>
<li>改变 <code>window</code> 大小</li>
<li>改变字体</li>
<li>添加或删除样式</li>
<li>文字改变</li>
<li>定位或者浮动</li>
<li>盒模型</li>
</ul>
<p>并且很多人不知道的是，重绘和回流其实也和 Eventloop 有关。</p>
<ol>
<li>当 Eventloop 执行完 Microtasks 后，会判断 <code>document</code> 是否需要更新，因为浏览器是 60Hz 的刷新率，每 16.6ms 才会更新一次。</li>
<li>然后判断是否有 <code>resize</code> 或者 <code>scroll</code> 事件，有的话会去触发事件，所以 <code>resize</code> 和 <code>scroll</code> 事件也是至少 16ms 才会触发一次，并且自带节流功能。</li>
<li>判断是否触发了 media query</li>
<li>更新动画并且发送事件</li>
<li>判断是否有全屏操作事件</li>
<li>执行 <code>requestAnimationFrame</code> 回调</li>
<li>执行 <code>IntersectionObserver</code> 回调，该方法用于判断元素是否可见，可以用于懒加载上，但是兼容性不好</li>
<li>更新界面</li>
<li>以上就是一帧中可能会做的事情。如果在一帧中有空闲时间，就会去执行 <code>requestIdleCallback</code> 回调。</li>
</ol>
<p>以上内容来自于 <a target="_blank" href="https://link.juejin.im/?target=https%3A%2F%2Fhtml.spec.whatwg.org%2Fmultipage%2Fwebappapis.html%23event-loop-processing-model" rel="nofollow noopener noreferrer">HTML 文档</a>。</p>
<p>既然我们已经知道了重绘和回流会影响性能，那么接下来我们将会来学习如何减少重绘和回流的次数。</p>
<h3 class="heading" data-id="heading-7">减少重绘和回流</h3>
<ul>
<li>使用 <code>transform</code> 替代 <code>top</code></li>
</ul>
<pre><code class="hljs html" lang="html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"test"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-class">.test</span> {
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">top</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100px</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">100px</span>;
    <span class="hljs-attribute">background</span>: red;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  setTimeout(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
    <span class="hljs-comment">// 引起回流</span>
    <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.test'</span>).style.top = <span class="hljs-string">'100px'</span>
  }, <span class="hljs-number">1000</span>)
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre><ul>
<li>
<p>使用 <code>visibility</code> 替换 <code>display: none</code> ，因为前者只会引起重绘，后者会引发回流（改变了布局）</p>
</li>
<li>
<p>不要把节点的属性值放在一个循环里当成循环里的变量</p>
<pre><code class="hljs js" lang="js"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1000</span>; i++) {
    <span class="hljs-comment">// 获取 offsetTop 会导致回流，因为需要去获取正确的值</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.test'</span>).style.offsetTop)
}
</code></pre></li>
<li>
<p>不要使用 <code>table</code> 布局，可能很小的一个小改动会造成整个 <code>table</code> 的重新布局</p>
</li>
<li>
<p>动画实现的速度的选择，动画速度越快，回流次数越多，也可以选择使用 <code>requestAnimationFrame</code></p>
</li>
<li>
<p>CSS 选择符<strong>从右往左</strong>匹配查找，避免节点层级过多</p>
</li>
<li>
<p>将频繁重绘或者回流的节点设置为图层，图层能够阻止该节点的渲染行为影响别的节点。比如对于 <code>video</code> 标签来说，浏览器会自动将该节点变为图层。</p>
<p></p><figure><img class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2018/3/29/1626fb6f33a6f9d7?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1280" data-height="619" src="./13-浏览器渲染原理_files/1626fb6f33a6f9d7"><figcaption></figcaption></figure><p></p>
<p>设置节点为图层的方式有很多，我们可以通过以下几个常用属性可以生成新图层</p>
<ul>
<li><code>will-change</code></li>
<li><code>video</code>、<code>iframe</code> 标签</li>
</ul>
</li>
</ul>
<h2 class="heading" data-id="heading-8">思考题</h2>
<blockquote class="warning"><p>思考题：在不考虑缓存和优化网络协议的前提下，考虑可以通过哪些方式来最快的渲染页面，也就是常说的关键渲染路径，这部分也是性能优化中的一块内容。
</p></blockquote><p>首先你可能会疑问，那怎么测量到底有没有加快渲染速度呢</p>
<p></p><figure><img class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2018/11/27/16754b5a3511198f?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="838" data-height="344" src="./13-浏览器渲染原理_files/16754b5a3511198f"><figcaption></figcaption></figure><p></p>
<p>当发生 <code>DOMContentLoaded</code> 事件后，就会生成渲染树，生成渲染树就可以进行渲染了，这一过程更大程度上和硬件有关系了。</p>
<p><strong>提示如何加速：</strong></p>
<ol>
<li>从文件大小考虑</li>
<li>从 <code>script</code> 标签使用上来考虑</li>
<li>从 CSS、HTML 的代码书写上来考虑</li>
<li>从需要下载的内容是否需要在首屏使用上来考虑</li>
</ol>
<p>以上提示大家都可以从文中找到，同时也欢迎大家踊跃在评论区写出你的答案。</p>
<h2 class="heading" data-id="heading-9">小结</h2>
<p>以上就是我们这一章节的内容了。在这一章节中，我们了解了浏览器如何将文件渲染为页面，同时也掌握了一些优化的小技巧。这部分的内容理解起来不大容易，如果大家对于这个章节的内容存在疑问，欢迎在评论区与我互动。</p>
</div><section data-v-05bbf43a="" class="book-comments"><div data-v-05bbf43a="" class="box-title">留言</div><div data-v-05bbf43a="" class="comment-box"><div data-v-81313b1e="" data-v-05bbf43a="" class="comment-form comment-form" id="comment"><div data-v-3b1ba6d2="" data-v-afcc6e34="" data-v-81313b1e="" data-src="https://b-gold-cdn.xitu.io/v3/static/img/default-avatar.e30559a.svg" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://b-gold-cdn.xitu.io/v3/static/img/default-avatar.e30559a.svg&quot;);"></div><textarea data-v-81313b1e="" placeholder="评论将在后台进行审核，审核通过后对所有人可见" class="content-input" style="overflow: hidden; overflow-wrap: break-word; height: 60px;"></textarea><div data-v-81313b1e="" class="action-box" style="display: none;"><div data-v-680eb36d="" data-v-81313b1e="" class="image-uploader image-uploader" style="display: none;"><input data-v-680eb36d="" type="file" class="input"><button data-v-680eb36d="" class="upload-btn"><i data-v-680eb36d="" class="icon ion-image"></i><span data-v-680eb36d="">上传图片</span></button></div><div data-v-81313b1e="" class="submit-box"><span data-v-81313b1e="" class="submit-text">Ctrl or ⌘ + Enter</span><button data-v-81313b1e="" class="submit-btn">评论</button></div></div><!----></div></div><ul data-v-32e5a55b="" data-v-05bbf43a="" st:block="commentList" class="comment-list comment-list"><!----></ul></section></div></div><!----><!----></div></div><div data-v-a9263a68="" data-v-097468bb="" class="book-handle book-direction"><div data-v-a9263a68="" class="step-btn step-btn--prev"><img data-v-a9263a68="" src="./13-浏览器渲染原理_files/prev.87ad47e.svg"></div><div data-v-a9263a68="" class="step-btn step-btn--next"><img data-v-a9263a68="" src="./13-浏览器渲染原理_files/next.54d8a35.svg"></div><!----><!----></div><!----></div></div></section><!----><!----><!----><div data-v-1b0b9cb8="" data-v-097468bb="" class="image-viewer-box"><!----></div></div><!----></div>
      
      
      <script type="text/javascript" src="./13-浏览器渲染原理_files/runtime.5902a8b1cc2b7567f479.js.下载"></script><script type="text/javascript" src="./13-浏览器渲染原理_files/0.e205fcdd4d4b6767f462.js.下载"></script><script type="text/javascript" src="./13-浏览器渲染原理_files/1.cbb1f8f5dcdee0086c6a.js.下载"></script>
    </body></html>